﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using LinFu.IoC.Configuration.Interfaces;
using LinFu.IoC.Configuration;
using LinFu.IoC;
using LinFu.IoC.Interfaces;


namespace CoreEx.DynamicInvoker.Implementation
{
    [Implements(typeof(IDynamicInvoker),LifecycleType.Singleton)]
    public class DynamicInvoker : IDynamicInvoker,IInitialize
    {
        private IMemberFinder _memberFinder;      
        private IMemberInvoker _memberInvoker;
        private static object lockObject = new object();
        #region IDynamicInvoker Members

        public object Invoke(object target, string memberName, params object[] arguments)
        {
            return _memberInvoker.Invoke(target, GetMember(target.GetType(), memberName,arguments), arguments);
        }

        public object Invoke(Type type,string memberName, params object[] arguments)
        {
            return _memberInvoker.Invoke(GetMember(type, memberName, arguments), arguments);
        }

        private MemberInfo GetMember(Type type, string memberName, params object[] arguments)
        {
            lock(lockObject)
            {
                var memberInfo = _memberFinder.GetMember(type, memberName, arguments);
                if (memberInfo == null)
                    throw new MissingMemberException(type.AssemblyQualifiedName, memberName);

                return memberInfo;
            }
        }


        #endregion

        #region IInitialize<IServiceContainer> Members

        public void Initialize(IServiceContainer source)
        {
            _memberFinder = source.GetService<IMemberFinder>();            
            _memberInvoker = source.GetService<IMemberInvoker>();
        }

        #endregion
    }
}
